package com.xu.skills.npe;

import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.util.Objects;
import java.util.Optional;

/**
 * @author xuguan
 * @date 2023/3/20
 * @desc 更加优雅的解决NPE问题
 */
public class NPESkill {
    private static final NpeUserEntity user;

    static {
        Address address = new Address();
        address.setProvince(null);

        Company company = new Company();
        company.setAddress(address);

        user = new NpeUserEntity();
        user.setCompany(company);
    }

    /**
     * 使用assert断言
     */
    public static String useAssert(NpeUserEntity user) {
        String province = "";

        // IDEA中默认assert(断言)是关闭，开启方式如下：
        // jvm的参数，参数是-enableassertions或者-ea（推荐）
        assert user != null : "用户不能为空";
        Company company = user.getCompany();

        // Spring工具类Assert
        Assert.notNull(company, "公司不能为空");
        Address address = company.getAddress();

        /*
          如果使用if,推荐使用工具类, 比如:
          StringUtils
          CollectionUtils
          ObjectUtils
          ...
         */
        if (Objects.nonNull(address)) {
            province = address.getProvince();
        }

        if (StringUtils.isEmpty(province)) {
            province = getDefaultProvince();
        }
        return province;
    }

    /**
     * 使用Optional类
     */
    public static String useOptional(NpeUserEntity user) {
        String province = Optional
                .ofNullable(user)
                .map(NpeUserEntity::getCompany)
                .map(Company::getAddress)
                .map(Address::getProvince)
                .orElseGet(() -> getDefaultProvince());
        /*
         推荐使用orElseGet()来获取默认值!!!因为orElseGet()方法只有前面的所有方法执行完后如果仍为null才会执行,
         而orElse()方法会在所有方法之前被执行
         */
        return province;
    }

    private static String getDefaultProvince() {
        System.out.println("======修改了数据库======");
        return "浙江省";
    }

    public static void main(String[] args) {
        System.out.println(useOptional(user));
        System.out.println(useAssert(user));
    }
}
